﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Threading;

namespace FotoButh
{
    public partial class FormFotoButh : Form
    {
        private static string IMAGE_URL = "http://10.220.196.190/jpeg";
        private static string COM_PORT = "COM3";

        private SnatchImage _snatchImage = new SnatchImage();
        private ButtonNotifier _buttonNotifier = new ButtonNotifier();
        private bool _isFullScreen = false;
        private volatile bool _pauseLive = false;
        private volatile bool _skipIncomingImage = false;
        private bool _canPushButton = true;

        public FormFotoButh()
        {
            InitializeComponent();
            ConnectEvents();
            _buttonNotifier.ComPort = COM_PORT;
            _snatchImage.ImageUri = new Uri(IMAGE_URL);
            textBoxIp.Text = IMAGE_URL;
            textBoxComPort.Text = COM_PORT;
            ContinuallyUpdate();
        }

        protected override void Dispose(bool disposing)
        {
            if (disposing && (components != null))
            {
                DisconnectEvents();
                components.Dispose();
            }
            base.Dispose(disposing);
        }

        private void FormFotoButh_KeyPress(object sender, KeyPressEventArgs e)
        {
            if (e.KeyChar == 27)
            {
                if (_isFullScreen)
                    RestoreScreen();
                else
                    FullScreen();
                e.Handled = true;
            }
        }

        private void textBoxComPort_TextChanged(object sender, EventArgs e)
        {
            try
            {
                COM_PORT = textBoxComPort.Text.ToUpper();
                _buttonNotifier.ComPort = COM_PORT;
            }
            catch (Exception)
            {
            }
        }

        private void textBoxIp_TextChanged(object sender, EventArgs e)
        {
            try
            {
                IMAGE_URL = textBoxIp.Text;
                _snatchImage.ImageUri = new Uri(IMAGE_URL);
            }
            catch (Exception)
            {
            }
        }

        private void ButtonNotifier_ButtonPushed(object sender, EventArgs e)
        {
            if (InvokeRequired)
            {
                BeginInvoke(new EventHandler(ButtonNotifier_ButtonPushed), new object[] { sender, e });
                return;
            }

            if (!this._canPushButton)
            {
                return;
            }
            this._canPushButton = false;
            this._skipIncomingImage = true;
            this._pauseLive = true;
            for (int i = 4; i > 0; i--)
            {
                Bitmap image = new Bitmap(string.Format("{0}.png", i));
                this.pictureBoxDisplay.Image = image;
                Application.DoEvents();
                Thread.Sleep(1000);
            }
            this.NullifyImages();
            this._skipIncomingImage = false;
            this.SwapPanels();
            for (int j = 0; j < 4; j++)
            {
                this.TakePicture(j + 1);
                Application.DoEvents();
                Thread.Sleep(2000);
            }
            Application.DoEvents();
            Thread.Sleep(3000);
            this.NullifyImages();
            this.SwapPanels();
            this._pauseLive = false;
            this._canPushButton = true;
        }

        private void TakePicture(int panelNumber)
        {
            this.FlashWhite(panelNumber);
            this._snatchImage.UpdateAndSave(panelNumber);
        }

        private void FlashWhite(int panelNumber)
        {
            PictureBox pictureBox = this.GetPictureBox(panelNumber);
            pictureBox.BackColor = Color.White;
            Application.DoEvents();
            Thread.Sleep(125);
            pictureBox.BackColor = Color.Black;
            Application.DoEvents();
        }

        private void ContinuallyUpdate()
        {
            ThreadPool.QueueUserWorkItem(delegate(object obj)
            {
                while (true)
                {
                    if (!this._pauseLive)
                    {
                        this._snatchImage.Update();
                    }
                    Thread.Sleep(66);
                }
            });
        }

        private void ButtonNotifier_ComLost(object sender, EventArgs e)
        {
            if (InvokeRequired)
            {
                BeginInvoke(new EventHandler(ButtonNotifier_ComLost), new object[] { sender, e });
                return;
            }
            textBoxComPort.ForeColor = Color.Red;
        }

        private void ButtonNotifier_ComFound(object sender, EventArgs e)
        {
            if (InvokeRequired)
            {
                BeginInvoke(new EventHandler(ButtonNotifier_ComFound), new object[] { sender, e });
                return;
            }
            textBoxComPort.ForeColor = Color.Green;
        }

        private void SnatchImage_GotImage(object arg1, Image arg2)
        {
            if (InvokeRequired)
            {
                BeginInvoke(new Action<object, Image>(SnatchImage_GotImage), new object[] { arg1, arg2 });
                return;
            }
            if (!this._skipIncomingImage)
            {
                if (arg2.Tag == null)
                {
                    this.pictureBoxDisplay.Image = arg2;
                    return;
                }
                int panelNumber = Convert.ToInt32(arg2.Tag);
                PictureBox pictureBox = this.GetPictureBox(panelNumber);
                pictureBox.Image = arg2;
            }
        }

        private PictureBox GetPictureBox(int panelNumber)
        {
            PictureBox result = null;
            switch (panelNumber)
            {
                case 1:
                    result = this.pictureBox1;
                    break;
                case 2:
                    result = this.pictureBox2;
                    break;
                case 3:
                    result = this.pictureBox3;
                    break;
                case 4:
                    result = this.pictureBox4;
                    break;
            }
            return result;
        }

        private void ConnectEvents()
        {
            _buttonNotifier.ButtonPushed += new EventHandler(ButtonNotifier_ButtonPushed);
            _buttonNotifier.ComFound += new EventHandler(ButtonNotifier_ComFound);
            _buttonNotifier.ComLost += new EventHandler(ButtonNotifier_ComLost);
            _snatchImage.GotImage += new Action<object, Image>(SnatchImage_GotImage);
        }

        private void DisconnectEvents()
        {
            _buttonNotifier.ButtonPushed -= new EventHandler(ButtonNotifier_ButtonPushed);
            _buttonNotifier.ComFound -= new EventHandler(ButtonNotifier_ComFound);
            _buttonNotifier.ComLost -= new EventHandler(ButtonNotifier_ComLost);
            _snatchImage.GotImage -= new Action<object, Image>(SnatchImage_GotImage);
        }

        private void NullifyImages()
        {
            this.pictureBoxDisplay.Image = null;
            this.pictureBox1.Image = null;
            this.pictureBox2.Image = null;
            this.pictureBox3.Image = null;
            this.pictureBox4.Image = null;
        }

        private void SwapPanels()
        {
            Control value = this.panelMainDisplay.Controls[0];
            this.panelMainDisplay.Controls.Add(this.panelStandby.Controls[0]);
            this.panelStandby.Controls.Add(value);
        }

        private void FullScreen()
        {
            this.panelConfig.Visible = false;
            this.panelStandby.Visible = false;
            base.Width = Screen.PrimaryScreen.WorkingArea.Width;
            base.Height = Screen.PrimaryScreen.WorkingArea.Height;
            this.BackColor = Color.Black;
            base.FormBorderStyle = FormBorderStyle.None;
            base.StartPosition = FormStartPosition.Manual;
            base.Top = 0;
            base.Left = 0;
            base.WindowState = FormWindowState.Maximized;
            this._isFullScreen = true;
        }

        private void RestoreScreen()
        {
            this.panelConfig.Visible = true;
            this.tableLayoutPanelQuad.Visible = true;
            base.Width = 400;
            base.Height = 320;
            this.BackColor = Color.FromKnownColor(KnownColor.Control);
            base.FormBorderStyle = FormBorderStyle.Sizable;
            base.StartPosition = FormStartPosition.WindowsDefaultLocation;
            base.Top = 100;
            base.Left = Screen.PrimaryScreen.WorkingArea.Width / 2 - 200;
            base.WindowState = FormWindowState.Normal;
            this._isFullScreen = false;
        }
    }
}